Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
A Elettrolandia si va a votare per eleggere il nuovo Governatore. Si presentano quattro candidati: 1,2,3,4.
Le schede votate sono raccolte in una lista, in cui ogni elemento memorizza il numero del candidato votato e un'informazione
sulla validità della scheda (valida o nulla). Si deve procedere allo spoglio.
(i) Definire gli opportuni tipi di dato per rappresentare la lista delle schede votate
(ii) Progettare una funzione ricorsiva che, presa in input la lista delle schede votate, e un numero corrispondente
ad uno dei candidati, proceda al conteggio dei voti validi relativi a quel candidato
(iii) Progettare una funzione che, presa in input la lista delle schede votate, e il numero corrispondente ad uno dei candidati,
elimini dalla lista iniziale le schede votate non valide di quel
candidato e restituisca il numero di cancellazioni effettuate
Ora credo di aver risolto tutto, ma se nella funzione del punto iii (EliminaSchedeNulle()) uso f (parametro) al posto di first (puntatore dichiarato globalmente per comodità) nel momento in cui vado a stampare la lista ho elementi in più che non dovrebbero esserci (se ho capito bene perchè first viene passato alla funzione per valore);
Quindi sostanzialmente la domanda è questa: cosa devo modificare nel codice per fare in modo che quando cambio il valore di f (cioè l'indirizzo dell'inizio della lista) nella funzione, venga cambiato anche il valore di first? Come posso, cioè, passare per riferimento first a EliminaSchedeNulle()?
int ConteggioVotiValidi (int candidato, scheda* f)//sto passando come parametro la lista solo perchè è richiesto esplicitamente nell'esercizio, ne farei a meno sfruttando il puntatore first che è dichiarato globalmente
{
if(f==NULL)return0;//controlla che la lista non sia vuota
if(f->candidato==candidato && f->valida==true)
return 1+ConteggioVotiValidi(candidato, f->next);
else
return 0+ConteggioVotiValidi(candidato,f->next);
}
//Fine Punto (ii)
// punto (iii)
int EliminaSchedeNulle(int candidato, scheda *f)//vedi commento a riga 132
{
if(first ==NULL)return0;//Se la lista è vuota esce dalla funzione tornando 0
if(first->next==NULL&& first->candidato==candidato && first->valida==false){InizializzaLista();return1;}//Nel caso in cui ci sia un solo elemento nella lista e questo elemento va eliminato, è necessario chiamare inizializzalista(); torna 1 perchè è coem fare una cancellazione
int cancellazioni=0;
scheda *temp, *prec;
//Il primo ciclo fa in modo che f non sia un voto nullo al candidato passato come parametro
while(first->candidato==candidato && first->valida==false){//fin quando la prima scheda è un voto nullo a candidato
temp=first->next;//il primo elemento diviene quello successivo
free(first);//libero la memoria del vecchio primo elemento
first=temp;
cancellazioni++;//incremento il numero di cancellazioni
}
prec=first;//ho gia verificato che f non è una scheda nulla a candidato
temp=prec->next;//controllo della scheda successiva alla prima "rimasta"
prec->next=temp->next;//Se la scheda puntata da temp non è valida allora la scheda precedente a temp (con prec->next=temp) dovrà puntare alla scheda successiva a temp (temp->next)
free(temp);//Libero la memoria
cancellazioni++;//incremento il numero di cancellazioni
temp=prec->next;
}else
{
prec=temp;//incremento prec
temp=temp->next;//incremento temp
}
};
return cancellazioni;//torna in output il numero delle cancellazioni effettuate
}
// punto (iii)
Ultima modifica effettuata da WinstonS il 12/12/2010 alle 22:49
per passare un valore per riferimento invece che per valore usa un puntatore a un puntatore...così puoi modificare il puntatore facendolo puntare da qualche altra parte...
Mai usati puntatori a puntatori; vediamo
il prototipo della funzione di questo tipo?
int EliminaSchedeNulle(int candidato, scheda **f)
e la chiamata alla funzione così? EliminaSchedeNulle(candidato,&first)[\code], dove candidato è un int e first è dichiarato come scheda *first[\code]...
E fin qui il programma va ma poi come opero all'interno di EliminaSchedeNulle?? *f->, *f., **f->, **f., (per fare un esempio di cose che non funzionano)?
Ecco così sembra andare (mi suggeriva lumo_e che si potrebbe semplificare la funzione EliminaSchedeNulle(...) ad un solo while, ma non sono arrivato a come fare).
Lo metto qui così che il post possa servire a qualcun altro.
int ConteggioVotiValidi (int candidato, scheda* f)
{
if(f==NULL)return0;//controlla che la lista non sia vuota
if(f->candidato==candidato && f->valida==true)
return 1+ConteggioVotiValidi(candidato, f->next);
else
return 0+ConteggioVotiValidi(candidato,f->next);
}
//Fine Punto (ii)
int EliminaSchedeNulle(int candidato, scheda** f)
{
if((*f)==NULL)return0;//Se la lista è vuota esce dalla funzione tornando 0
if((*f)->next==NULL&&(*f)->candidato==candidato &&(*f)->valida==false){InizializzaLista(f);return1;}//Nel caso in cui ci sia un solo elemento nella lista e questo elemento va eliminato, è necessario chiamare inizializzalista(); torna 1 perchè è coem fare una cancellazione
int cancellazioni=0;
scheda *temp, *prec;
//Il primo ciclo fa in modo che f non sia un voto nullo al candidato passato come parametro
while((*f)->candidato==candidato &&(*f)->valida==false){//fin quando la prima scheda è un voto nullo a candidato
temp=(*f)->next;//il primo elemento diviene quello successivo
free((*f));//libero la memoria del vecchio primo elemento
(*f)=temp;
cancellazioni++;//incremento il numero di cancellazioni
}
prec=(*f);//ho gia verificato che f non sia una scheda nulla a candidato
temp=prec->next;//controllo della scheda successiva alla prima "rimasta"
prec->next=temp->next;//Se la scheda puntata da temp non è valida allora la scheda precedente a temp (con prec->next=temp) dovrà puntare alla scheda successiva a temp (temp->next)
free(temp);//Libero la memoria
cancellazioni++;//incremento il numero di cancellazioni
temp=prec->next;
}else
{
prec=temp;//incremento prec
temp=temp->next;//incremento temp
}
};
return cancellazioni;//torna in output il numero delle cancellazioni effettuate
}
// punto (iii)
Ultima modifica effettuata da WinstonS il 12/12/2010 alle 22:50
Mai usati puntatori a puntatori; vediamo
il prototipo della funzione di questo tipo?
int EliminaSchedeNulle(int candidato, scheda **f)
e la chiamata alla funzione così? EliminaSchedeNulle(candidato,&first)[\code], dove candidato è un int e first è dichiarato come scheda *first[\code]...
E fin qui il programma va ma poi come opero all'interno di EliminaSchedeNulle?? *f->, *f., **f->, **f., (per fare un esempio di cose che non funzionano)?
mi pare che devi usare (*f)->
in quanto l'operatore -> ha la precedenza su *...
Un altro modo sarebbe di tenere un puntatore numerico che conitene il numero di strutture allocate e un bool che dice se la struttura va salvata o no.
Una volta creata la funzione di input sembre di programmare in python,basta solo liberare l' area di memoria (io non lo faccio perchè è un programma breve).
Codice sorgente - presumibilmente C++
#include <stdio.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
typedefstruct
{
bool save;
char*nome;
char*cognome;
}persona;
char*input(FILE*fp);
void add(persona *ptr,int*num);
int main(int argc,char**argv)
{
persona *lista;
int*num,i;
num=(int*)malloc(sizeof(int));
lista=(persona*)malloc(sizeof(persona));
*num=0;
for(i=0;i<3;i++)
add(lista,num);
printf("Output:\n");
for(i=0;i<*num;i++)
puts(lista[i].cognome);
return0;
}
char*input (FILE*fp)
{
char*string;
char check;
string=(char*)malloc(sizeof(char));
int i=1;
while((check=fgetc(fp))!=10)
{
string[i-1]=check;
i++;
string=(char*)realloc(string,i*sizeof(char));
}
string[i-1]='\0';
fflush(stdin);
return string;
}
void add(persona *ptr,int*num)
{
if(*num>1)
ptr=(persona*)realloc(ptr,sizeof(persona));
printf("Inserire nome:-->");
ptr[*num].nome=input(stdin);
printf("Inserire cognome:-->");
ptr[*num].cognome=input(stdin);
ptr[*num].save=true;
(*num)++;
}
Ovviamente se non hai tempo di cambiarlo ti conviene lasciarlo così,molti usando il puntatore alla prossima struttura.
Ma in questo modo per aggiungerne una basta digitare (add,num),per cancellarne una basta mettere a falso il bool che dice di salvarla o no.
Alla fine del programma solo quelle col bool true vengono salvate sul file.